package chapter15;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2019/2/23 11:30
 *
 * 使用wait()/notifyAll()的缺陷是只有一个条件等待队列(take/put方法与其他方法使用同一个等待队列)，如果除了get/put，还有其他的同步方法时，可能会发生与自己无关的方法调用将自己唤醒，例如其他同步方法中也使用了notify()/nofityAll()方法，则所有通过实例锁对象this实现阻塞的地方都会被唤醒，进行判断后才知道是否是自己的条件改变。
 *
 * 并且在分析等待条件的时候比较复杂，可能由于其他方法竞争占用了锁的使用。
 */
public class MyBlockingQueue<E> {
    private Queue<E> queue = null;
    private int limit;

    public MyBlockingQueue(int limit) {
        this.limit = limit;
        queue = new ArrayDeque<>(limit);
    }

    public synchronized void put(E e) throws InterruptedException {
        while (queue.size() == limit) {
            wait();
        }
        queue.add(e);
        notifyAll();
    }

    public synchronized E take() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        E e = queue.poll();
        notifyAll();
        return e;
    }
}
